package com.zeus.core.base;

import com.zeus.common.constants.ZeusConstant;
import com.zeus.common.enums.ZeusSenderTypeEnum;
import com.zeus.common.utils.CacheUtils;
import com.zeus.core.report.ZeusReportClient;
import com.zeus.core.report.ZeusReportErrorClient;

/**
 * 自我保护
 *
 * @author f1ybear_wang  2022/3/8 5:35 下午
 */
public abstract class AbstractZeusSelfProtection {

    /**
     * 是否可以发送消息
     *
     * @author f1ybear_wang  2022/3/8 5:37 下午
     */
    protected boolean isCanSendMessage() {
        return CacheUtils.get(getErrorLockKey()) == null;
    }

    /**
     * 是否可以发送消息
     * 
     * @param typeEnum 发送者枚举
     * @author f1ybear_wang  2022/3/8 5:37 下午
     */
    protected boolean isCanSendMessage(ZeusSenderTypeEnum typeEnum) {
        if (typeEnum == null) {
            return false;
        }
        return CacheUtils.get(getErrorLockKey(typeEnum)) == null;
    }

    /**
     * 消息发送失败
     *
     * @author f1ybear_wang  2022/3/8 5:37 下午
     */
    protected void sendMessageFail() {
        int errorCount = CacheUtils.incr(getErrorCountKey());
        if (errorCount > ZeusConstant.SEND_ERROR_COUNT_MAX) {
            sendMessageLock();
        }
    }

    /**
     * 消息发送失败
     *
     * @param senderType 发送者枚举
     * @author f1ybear_wang  2022/3/8 5:37 下午
     */
    protected void sendMessageFail(ZeusSenderTypeEnum senderType) {
        int errorCount = CacheUtils.incr(getErrorCountKey(senderType));
        if (errorCount > ZeusConstant.SEND_ERROR_COUNT_MAX) {
            sendMessageLock(senderType);
        }
    }

    private void sendMessageLock() {
        CacheUtils.put(getErrorLockKey(), true);
        ZeusReportClient client = new ZeusReportErrorClient("消息发送失败次数过多, 服务暂停~");
        client.complete();
    }

    private void sendMessageLock(ZeusSenderTypeEnum senderType) {
        CacheUtils.put(getErrorLockKey(senderType), true);
        ZeusReportClient client = new ZeusReportErrorClient(senderType.getDescription() + "发送失败次数过多, 服务暂停~");
        client.complete();
    }

    private String getErrorLockKey() {
        return "zeus_send_error_lock:";
    }

    private String getErrorLockKey(ZeusSenderTypeEnum typeEnum) {
        return "zeus_send_" + typeEnum.getCode() + "_error_lock:";
    }

    private String getErrorCountKey() {
        return "zeus_send_error_count:";
    }

    private String getErrorCountKey(ZeusSenderTypeEnum typeEnum) {
        return "zeus_send_" + typeEnum.getCode() + "_error_count:";
    }
}
